%{
  import java.lang.Math;
  import java.io.*;
  import gas.frontend.*;
  import java.util.*;
%}
      
%token IF
%token ELSE
%token FOR
%token WHILE
%token BREAK
%token CONTINUE
%token RETURN
%token NEW
%token FUNCTION
%token <sval> TYPE
%token <sval> TRUE
%token <sval> FALSE
%token <ival> NUM
%token <dval> FLOAT
%token <sval>  ID
%token <sval> GASID
%token <sval> STRING
%token LPAREN
%token RPAREN
%token DOT
%token <obj> MULT
%token <obj> PLUS
%token <obj> MINUS
%token <obj> DIV
%token <obj> POWER
%token <obj> OR
%token <obj> AND
%token <obj> NOT
%token <obj> SEMI
%token <sval> LBRACE
%token <sval>RBRACE
%token LBLK
%token RBLK
%token <obj> ASGN
%token COMMA
%token <obj> GE
%token <obj> LE
%token <obj> GT
%token <obj> LT
%token <obj> EQL
%token <obj> NEQL
%token SHARP

%type <obj> expression
%type <obj> atom
%type <obj> lvalue
%type <obj> assign_stmt
%type <obj> decl_stmt
%type <obj> stmt
%type <obj> program_body
%type <obj> program
%type <obj> block
%type  <obj> if_stmt
%type <obj>  opt_array_init_list
%type <obj> for_stmt
%type <obj> opt_arrpos
%type <obj> while_stmt
%type <obj> act_arg_list
%type <obj> function_def
%type <obj> form_arg_list
%type <obj> opt_form_arg_list
%type <obj> func_body
%type <obj> func_call_stmt
%type <obj> programfile
%type <obj> break_stmt
%type <obj> continue_stmt
%type <obj> stmt_list
%type <obj> return_stmt

%left OR
%left AND
%right NOT
%left GE LE GT LT EQL NEQL
%left PLUS MINUS
%left MULT DIV
%right POWER



%%

programfile : program {

                                            TreeNode p = new TreeNode(); 
                                            p.code = new String(((TreeNode)$1).code);
                                            $$ = (Object) p;
                                            System.out.println(p.code);
                                            //print to File
                                            icg.PrintToFile(p);

 }

program : program_body  {  TreeNode p = new TreeNode(); 
                                            p.code = new String(((TreeNode)$1).code);
                                            $$ = (Object) p;
                                         }
              |  function_def program
                                                            { 
                                                         TreeNode p = new TreeNode(); 
                                                         p.code = ((TreeNode)$1).code;
                                                         p.code += ((TreeNode)$2).code;
                                                         p.code = new String (p.code);
                                                         $$ = (Object) p; 
                                                             }
              ;

program_body : stmt program_body     {  TreeNode pb = new TreeNode(); 
                                                                pb.code = ((TreeNode)$1).code;
                                                                pb.code += ((TreeNode)$2).code;
                                                                $$ = (Object) pb; }
                       | { TreeNode pb = new TreeNode(); 
                            pb.code = "";
                            $$ = (Object) pb; }
                       ;

function_def : TYPE ID LPAREN { st.enterScope(); }  form_arg_list RPAREN func_body {

try {st.leaveScope();} 
                          catch (Exception e) {}
                                                               TreeNode function_def = new TreeNode();
                                                                 //Type = $1
                                                           try {
                                                           String newID = "FUN_" + func_st.registerfunction($2);
                                                           
                                                           function_def.code = "FUNDEF " + $1 + " " + newID  + ((TreeNode)$5).code + "\n";
                                                           function_def.code += ((TreeNode)$7).code;
                                                           function_def.code += "END\n";
                                                           $$ = (Object)function_def;
                                                           
                                                      }
                                                       catch (AlreadyDefinedFunctionException e) {
                                                           System.out.println("Already defined function error");
                                                           $$ = (Object) new TreeNode();
                                                      }

}
                    | ID LPAREN form_arg_list RPAREN func_body {}
                    ;

form_arg_list : TYPE ID opt_form_arg_list   {                      
                                                         TreeNode form_arg_list = new TreeNode();
                                
                                                           try {
                                                           String newID = st.register($2);
                                                         
                                                           // deal with init value
                                                           map.put(newID, new Symbol($2,  null));
                                                           form_arg_list.code = " " + $1 + " " + newID;                                                                                               form_arg_list.code += ((TreeNode)$3).code;
                                                           $$ = (Object)form_arg_list;
                                                           
                                                      }
                                                       catch (AlreadyDefinedVariableException e) {
                                                           System.out.println("Already defined variable error");
                                                           $$ = (Object) new TreeNode();
                                                      }
                     }
                     |   {TreeNode form_arg_list = new TreeNode();
                                  form_arg_list.code = "";
                                  $$ = (Object)form_arg_list;
                                }
                     ;

opt_form_arg_list : COMMA TYPE ID opt_form_arg_list   {
                                                                               TreeNode opt_form_arg_list = new TreeNode();
                                
                                                           try {
                                                           String newID = st.register($3);
                                                         
                                                           // deal with init value
                                                           map.put(newID, new Symbol($2,  null));
                                                           opt_form_arg_list.code = " " + $2 + " " + newID;
                                                           opt_form_arg_list.code += ((TreeNode)$4).code;
                                                           $$ = (Object)opt_form_arg_list;
                                                           
                                                      }
                                                       catch (AlreadyDefinedVariableException e) {
                                                           System.out.println("Already defined variable error");
                                                           $$ = (Object) new TreeNode();
                                                      }
                                                                                           }
                            |   {TreeNode opt_form_arg_list = new TreeNode();
                                  opt_form_arg_list.code = "";
                                  $$ = (Object)opt_form_arg_list;
                                }
                            ;

func_body :  LBRACE program_body RBRACE  { 
                                                                              TreeNode func_body = new TreeNode();
                                                                               func_body.code = ((TreeNode)$2).code;
                                                                               $$ = (TreeNode)func_body; 
                                                                            }
                 ; 


stmt : decl_stmt SEMI      {  
                                   $$ = (Object)$1; }
	| if_stmt           {

	 $$ = (Object)$1;
}
        | for_stmt                  {    $$ = (Object)$1;                 }
        | while_stmt              {       $$ = (Object)$1;         }
        | break_stmt  { $$ = (Object)$1; }
        | continue_stmt  { $$ = (Object)$1; }
        | return_stmt  { $$ = (Object)$1; }
        | assign_stmt SEMI  { 
                                   $$ = (Object)$1; }
        | expression SEMI            {                 $$ = (Object)$1;              }
        | {st.enterScope();} block  { 
                                                     TreeNode block = new TreeNode(); 
                                                     block.code = ((TreeNode)$2).code;
                                                     $$ = (Object) block;
                                                     try {
                                                          st.leaveScope();
                                                     } catch(Exception e) {} 
                                                 }
        ;

stmt_list : stmt stmt_list { TreeNode stmt = new TreeNode();
                           TreeNode stmt1 = (TreeNode)$1;
                           TreeNode stmt2 = (TreeNode)$2; 
                           stmt.code = stmt1.code + stmt2.code;
                           $$ = (Object) stmt;
         }
         | { TreeNode stmt_list = new TreeNode();
              stmt_list.code = "";
              $$ = (Object) stmt_list;
            }
        ;


decl_stmt : TYPE ID {                                                      
                                                      TreeNode decl_stmt = new TreeNode();
                                                      
                                                      try {
                                                           String newID = st.register($2);
                                                         
                                                           // deal with init value
                                                           map.put(newID, new Symbol($1,  null));
                                                           
                                                           decl_stmt.type = $1;
                                                           icg.ProcessDeclaration(decl_stmt, newID);
                                                           $$ = (Object) decl_stmt;                                                          
                                                      }
                                                       catch (AlreadyDefinedVariableException e) {
                                                           System.out.println("Already defined variable error");
                                                           $$ = (Object) new TreeNode();
                                                      }
                                                                            
                                            }
          | TYPE ID ASGN expression   {
         
                                         TreeNode decl_stmt = new TreeNode();
                                                      
                                                      try {
                                                           String newID = st.register($2);
                                                         
                                                           // deal with init value
                                                           map.put(newID, new Symbol($1,  null));
                                                           
                                                           decl_stmt.type = $1;
                                                           icg.ProcessDeclaration(decl_stmt, (TreeNode)$4 ,newID);
                                                           
                                                           $$ = (Object) decl_stmt;                                                          
                                                      }
                                                       catch (AlreadyDefinedVariableException e) {
                                                           System.out.println("Already defined variable error");
                                                           $$ = (Object) new TreeNode();
                                                      }
                                                                      
                                                                    }
          | TYPE ID LBLK NUM RBLK ASGN LBRACE expression opt_array_init_list RBRACE  {
                                                      TreeNode decl_stmt = new TreeNode();
                                                   try {
                                                           String newID = st.register($2);
                                                         
                                                           // deal with init value
                                                           map.put(newID, new Symbol($1,  null));
                                                           
                                                           decl_stmt.type = $1;
                                                           int size = $4;
                                                           icg.ProcessDeclaration(decl_stmt, size, ((TreeNode)$8), ((TreeNode)$9),newID, list);
                                                           
                                                           $$ = (Object) decl_stmt;                                                          
                                                      }
                                                       catch (AlreadyDefinedVariableException e) {
                                                           System.out.println("Already defined variable error");
                                                           $$ = (Object) new TreeNode();
                                                      }

                                                    list.clear();                  }
          | TYPE ID LBLK NUM RBLK      {
                                                                                  TreeNode decl_stmt = new TreeNode();
                                                      
                                                      try {
                                                           String newID = st.register($2);
                                                         
                                                           // deal with init value
                                                           map.put(newID, new Symbol($1,  null));
                                                           
                                                           decl_stmt.type = $1;
                                                            int size = $4;
                                                           icg.ProcessDeclaration(decl_stmt, size, newID);
                                                           $$ = (Object) decl_stmt;                                                          
                                                      }
                                                       catch (AlreadyDefinedVariableException e) {
                                                           System.out.println("Already defined variable error");
                                                           $$ = (Object) new TreeNode();
                                                      }  
                                                                                                                           }
          | TYPE ID ASGN NEW TYPE LPAREN act_arg_list RPAREN  {  
                                                             //MODIFIED BY DAVID
                                                                TreeNode decl_stmt = new TreeNode();   
                                                                 TreeNode actarglist =  (TreeNode) $7;
                                                         try {
                                                              String newID = st.register($2);
                                                            
                                                              // deal with init value
                                                              map.put(newID, new Symbol($1,  null));
                                                              decl_stmt.type = $1;
                                                               int size = list.size();
                                                              icg.ProcessConstructor(decl_stmt, size, ((TreeNode) $7), newID, list);
                                                              $$ = (Object) decl_stmt;                                                          
                                                         }
                                                          catch (AlreadyDefinedVariableException e) {
                                                              System.out.println("Already defined variable error");
                                                              $$ = (Object) new TreeNode();
                                                         }  
                                                                list.clear();
                                                     }
          | TYPE ID LBLK RBLK ASGN NEW TYPE LBLK NUM RBLK      {
                                                                                  TreeNode decl_stmt = new TreeNode();
                                                      
                                                      try {
                                                           String newID = st.register($2);
                                                         
                                                           // deal with init value
                                                           map.put(newID, new Symbol($1,  null));
                                                           
                                                           decl_stmt.type = $1;
                                                            int size = $9;
                                                           icg.ProcessDeclaration(decl_stmt, size, newID);
                                                           $$ = (Object) decl_stmt;                                                          
                                                      }
                                                       catch (AlreadyDefinedVariableException e) {
                                                           System.out.println("Already defined variable error");
                                                           $$ = (Object) new TreeNode();
                                                      }  
                                                                                                                           }
          ;

opt_array_init_list : COMMA expression opt_array_init_list   {  TreeNode optarrayinitlist = new TreeNode();
                                                                                                TreeNode optarrayinitlist1 = (TreeNode)$3;
                                                                                                TreeNode exp = (TreeNode) $2;
                                                                                                optarrayinitlist.code = exp.code;                                                                
                                                                                                list.add(exp.addr);
                                                                                                optarrayinitlist.code += optarrayinitlist1.code;
                                                                                                $$ = (Object) optarrayinitlist;     
                                                                                          }					
                            |  { TreeNode opt = new TreeNode();
                                  opt.code = "";
                                  $$ = (Object) opt; 
                               }
                            ;


if_stmt : IF LPAREN expression RPAREN stmt  {
                     TreeNode if_stmt = new TreeNode();

                     if_stmt.next = icg.NewLabel();

                     TreeNode expr = (TreeNode)$3;

                     TreeNode stmt = (TreeNode)$5;

                     if_stmt.code = expr.code + "iffalse " + expr.addr;
                     if_stmt.code += " goto " + if_stmt.next + "\n";
                     if_stmt.code += stmt.code + "Label " + if_stmt.next + "\n";

                     $$ = (Object)if_stmt;
          }
        | IF LPAREN expression RPAREN stmt ELSE stmt {
                     TreeNode if_stmt = new TreeNode();
                     String gotoElse = icg.NewLabel();

                     if_stmt.next = icg.NewLabel();

                     TreeNode expr = (TreeNode)$3;

                     TreeNode stmt1 = (TreeNode)$5;
                     TreeNode stmt2 = (TreeNode)$7;

                     if_stmt.code = expr.code + "iffalse " + expr.addr;
                     if_stmt.code += " goto " + gotoElse + "\n";
                     if_stmt.code += stmt1.code + "goto " + if_stmt.next + "\n";
                     if_stmt.code += "Label " + gotoElse + "\n" + stmt2.code;
                     if_stmt.code += "Label " + if_stmt.next + "\n";

                     $$ = (Object)if_stmt;
          }
        ;

for_stmt : FOR { LoopIni.add(icg.NewLabel()); LoopTer.add(icg.NewLabel()); }LPAREN assign_stmt SEMI expression SEMI assign_stmt RPAREN stmt
                                                                        {   TreeNode for_stmt = new TreeNode();
                                 icg.ProcessFor(for_stmt, ((TreeNode)$4), ((TreeNode)$6), ((TreeNode)$8), ((TreeNode)$10), LoopIni.get(LoopIni.size()-1), LoopTer.get(LoopTer.size()-1));  
                                                                        LoopIni.remove(LoopIni.size()-1); 
                                                                        LoopTer.remove(LoopTer.size()-1);
                                                                         $$  = (Object)for_stmt;                       
                                                                        }
         ;

while_stmt : WHILE { LoopIni.add(icg.NewLabel()); LoopTer.add(icg.NewLabel()); }LPAREN expression RPAREN stmt  
                                                                       {
                                                                        TreeNode while_stmt = new TreeNode();
                                                                        icg.ProcessWhile(while_stmt, (TreeNode)$4, (TreeNode)$6, LoopIni.get(LoopIni.size()-1), LoopTer.get(LoopTer.size()-1));  
                                                                        LoopIni.remove(LoopIni.size()-1); 
                                                                        LoopTer.remove(LoopTer.size()-1);
                                                                        $$ = (Object)while_stmt;
                                                                       }
           ;

block : LBRACE stmt_list RBRACE  {   
                                                        TreeNode block = new TreeNode();
                                                        block.code =  ((TreeNode) $2).code;
                                                 
                                                        $$ = (Object) block;            
                                                    }
         |  LBRACE RBRACE  {TreeNode block = new TreeNode();
                                  block.code = "";
                                  $$ = (Object)block;
                                }
        ;

break_stmt : BREAK SEMI   {TreeNode break_stmt = new TreeNode();
                                    break_stmt.code = "goto " + LoopTer.get(LoopTer.size()-1) + "\n";
                                    $$ = (Object)break_stmt;}
           ;

continue_stmt : CONTINUE SEMI   {TreeNode continue_stmt = new TreeNode();
                                    continue_stmt.code = "goto " + LoopIni.get(LoopIni.size()-1) + "\n";
                                    $$ = (Object)continue_stmt;}
              ;
 
return_stmt : RETURN SEMI  {
                  TreeNode return_stmt = new TreeNode();
                  return_stmt.code = "return\n";
                  $$ = (Object) return_stmt;
              }
            | RETURN expression SEMI  {
                  TreeNode return_stmt = new TreeNode();
                  TreeNode expr = (TreeNode) $2;
                  return_stmt.code = expr.code + "return " + expr.addr + "\n";
                  $$ = (Object) return_stmt;
              }
            ;

assign_stmt : lvalue ASGN expression  { 
  TreeNode assign_stmt = new TreeNode();
  TreeNode lvalue = (TreeNode)$1;
  TreeNode expr = (TreeNode)$3;
  assign_stmt.addr = lvalue.addr;
  assign_stmt.code = expr.code + lvalue.code + lvalue.addr + " " + expr.addr + "\n";
  $$ = (Object)assign_stmt;                                                      } 
       | lvalue ASGN NEW TYPE LPAREN act_arg_list RPAREN  {  
                                                             //MODIFIED BY DAVID
                                                                TreeNode assign_stmt = new TreeNode();  
                                                                TreeNode lvalue = (TreeNode)$1;          
                                                              int size = list.size();
                                                              assign_stmt.type = $4;
                                                              icg.ProcessConstructor(assign_stmt, size, ((TreeNode) $6), lvalue.addr, list);
                                                              $$ = (Object) assign_stmt;                                                          

                                                                list.clear();
                                                     }
            ;

lvalue : ID                     {
                                             TreeNode lvalue = new  TreeNode();
                                           
					   try{
					    
                                                                                       lvalue.addr=st.getID($1);
                                                                                       lvalue.code = "";
					       $$=(Object)lvalue;
					       }
					                                                                   catch (NotDefinedVariableException e) {
                                                                                       System.out.println("Not defined variable error");
                                                                                       $$ = (Object) new TreeNode();
                                                                                   }

		      }           
       | ID opt_arrpos{     TreeNode lvalue = new TreeNode();
                                     TreeNode opt_arrpos = (TreeNode)$2;
                                     lvalue.code = opt_arrpos.code;
                                        try {
                                                lvalue.addr = st.getID($1);
                                                lvalue.addr += "#" + opt_arrpos.addr;
                                                $$ = (Object)lvalue;
                                              }
                                      	   catch (NotDefinedVariableException e) {
                                                           System.out.println("Not defined variable error");
                                                           $$ = (Object) new TreeNode();
                                                      }



                              }
       ;


opt_arrpos : LBLK expression RBLK  { TreeNode opt_arrpos = new TreeNode();
                                                              TreeNode expression = (TreeNode)$2;
                                                                                   opt_arrpos.code = expression.code;
                                                                                   opt_arrpos.addr = expression.addr;
                                                                 $$ = (Object)opt_arrpos;

                                                                                }
           ;


func_call_stmt : ID LPAREN act_arg_list RPAREN    {  
                                                                TreeNode func_call_stmt = new TreeNode();
                                                                                             TreeNode act_arg_list = (TreeNode) $3;
                                                               String ID;
                                                                                             try 
                                                                                                 {
                                                                                                   ID = func_st.getFunctionID($1);
                                                                                                 }
                                                                                             catch (NotDefinedFunctionException e) {
                        System.out.println("Not defined function variable error or maybe it is a system function");
                                                                                                ID = $1;
                                                                                                 
                                                      }


                                                               
                                                                           func_call_stmt.addr = st.generateNewID();

                                                                           icg.ProcessFunCall(func_call_stmt, act_arg_list, ID, list);
                                                                                   $$ = (Object)func_call_stmt;
                                                                                                 list.clear();

                                                                                                    
                                                                                         }
              | lvalue DOT ID LPAREN act_arg_list RPAREN   {                                                                                                                                            TreeNode func_call_stmt = new TreeNode();
                                                               TreeNode act_arg_list = (TreeNode) $5;
                                                               String ID;
                                                               try
                                                               {
                                                                           ID = func_st.getFunctionID($3);
                                                                }
                                                                catch (NotDefinedFunctionException e) {
                           System.out.println("Not defined function variable error or maybe it is a system function");
                                                                    ID = $3;
                                                                }


                                                                                                                                                                                                       func_call_stmt.addr = st.generateNewID();

                                      icg.ProcessFunCall(((TreeNode)$1), func_call_stmt, act_arg_list, ID, list);
                                                                                   $$ = (Object)func_call_stmt;
                                                                   list.clear(); 
                                                
}
              ;


act_arg_list : expression      {  TreeNode act_arg_list = new TreeNode();
                                              TreeNode expression = (TreeNode)$1;
                                              act_arg_list.code = expression.code;
                                              act_arg_list.addr = expression.addr; 
                                              list.add(expression.addr);
                                              $$ = (Object) act_arg_list; }
             | expression COMMA act_arg_list   {  //MODIFIED BY DAVID
                                  TreeNode actarglist = new TreeNode();
                                  TreeNode actarglist1 = (TreeNode) $3;
                                  TreeNode expr = (TreeNode) $1;
                                  actarglist.code = expr.code;
                                  actarglist.code += actarglist1.code;
                                  list.add(expr.addr);
                                  $$ = (Object)actarglist;  }
             | { TreeNode act_arg_list = new TreeNode();
                  act_arg_list.code = "";
                  act_arg_list.addr = "";
                  $$ = (TreeNode) act_arg_list;
               }
             ;

expression : atom                  { 
                                                $$=(Object)$1;
                                            }
           | PLUS atom                                    {
	     TreeNode expression = new TreeNode();
             TreeNode atom = (TreeNode)$2;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = atom.code + newID + " " + "+" + " " + atom.addr + "\n";

$$ = (Object)expression;}
           | MINUS atom                                  {
	     TreeNode expression = new TreeNode();
             TreeNode atom = (TreeNode)$2;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = atom.code + newID + " " + "-" + " " + atom.addr + "\n";
$$ = (Object)expression;
}
           | NOT expression                            {
	     TreeNode expression = new TreeNode();
             TreeNode atom = (TreeNode)$2;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = atom.code + newID + " " + "!" + " " + atom.addr + "\n";

$$ = (Object)expression;}
           | expression OR expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " || " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression AND expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " && " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression GE expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " >= " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression LE expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " <= " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression GT expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " > " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression LT expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " < " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression EQL expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " == " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression NEQL expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " != " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression PLUS expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " + " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression MINUS expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " - " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression MULT expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " * " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression DIV expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " / " +expr2.addr + "\n";
           $$ = (Object)expression;}
           | expression POWER expression                 {
	     TreeNode expression = new TreeNode();
             TreeNode expr1 = (TreeNode)$1;
             TreeNode expr2 = (TreeNode)$3;
             String newID = st.generateNewID();
             expression.addr = newID;
             expression.code = expr1.code + expr2.code + newID + " " + expr1.addr + " ^ " +expr2.addr + "\n";
           $$ = (Object)expression;}
           ;
  

atom : STRING                                      {TreeNode atom = new TreeNode(); 
                                         atom.code="";
					   atom.addr=icg.StringTranform($1);
                                          $$=(Object)atom; }
     | GASID                                      {TreeNode atom = new TreeNode(); 
                                         atom.code="";
					   atom.addr=$1;
                                          $$=(Object)atom; }
     | NUM        {
                                         TreeNode atom = new TreeNode(); 
                                         atom.code="";
                                         atom.addr=String.valueOf($1);
                                          $$=(Object)atom; }
     | FLOAT   {
                                         TreeNode atom = new TreeNode(); 
                                         atom.code="";
                                         atom.addr=String.valueOf($1);
                                          $$=(Object)atom; }
     | TRUE           {TreeNode atom = new TreeNode(); 
                                         atom.code="";
                                         atom.addr=$1;
                                          $$=(Object)atom; }
     | FALSE         {TreeNode atom = new TreeNode(); 
                                         atom.code="";
                                         atom.addr=$1;
                                          $$=(Object)atom; }
     | lvalue              {
       $$=(Object)$1; }
     | func_call_stmt  { $$=(Object)$1; }
     | LPAREN expression RPAREN  {$$ = (Object)$2;}
     ;





%%

/* a reference to the lexer object */
private Yylex lexer;

/* interface to the lexer */
private int yylex () {
    int yyl_return = -1;
    try {
      yylval = new ParserVal(0);
      yyl_return = lexer.yylex();
    }
    catch (IOException e) {
      System.err.println("IO error :"+e);
    }
    return yyl_return;
  }

/* error reporting */
public void yyerror (String error) {
    System.err.println ("Error: " + error);
  }

/* lexer is created in the constructor */
public Parser(Reader r) {
    lexer = new Yylex(r, this);
  }

SymbolTable st = new SymbolTable();
SymbolTable func_st = new SymbolTable();
StorageMap  map = new StorageMap();

IntermediateCodeGenerator icg = new IntermediateCodeGenerator("/Users/youhansun/Documents/course09fall/COMSW4115/test/source.o", map);

ArrayList<String> list = new ArrayList<String>();

ArrayList<String> LoopIni = new ArrayList<String>();
ArrayList<String> LoopTer = new ArrayList<String>();

int i = 0;
